using Microsoft.Extensions.Logging;
using Uantek.Device.Communication.Devices;
using Uantek.Device.Communication.Models;
using Uantek.Device.Communication.Protocols.Modbus;
using Uantek.Device.Communication.Utilities;

namespace Uantek.Device.Communication.Examples
{
    /// <summary>
    /// Modbus通信示例
    /// </summary>
    public class ModbusCommunicationExample
    {
        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly ILogger<ModbusCommunicationExample>? _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志记录器</param>
        public ModbusCommunicationExample(ILogger<ModbusCommunicationExample>? logger = null)
        {
            _logger = logger;
        }

        /// <summary>
        /// Modbus TCP通信示例
        /// </summary>
        /// <returns>任务</returns>
        public async Task ModbusTcpExampleAsync()
        {
            ModbusDevice? device = null;
            try
            {
                _logger?.LogInformation("开始Modbus TCP通信示例");

                // 1. 创建连接字符串
                var connectionBuilder = new ConnectionStringBuilder(_logger)
                    .SetModbusTcpParameters("192.168.1.100", 502, 1, 5000);

                var connectionString = connectionBuilder.Build();
                _logger?.LogInformation("连接字符串: {ConnectionString}", connectionString);

                // 2. 创建协议和传输实例
                var protocol = new ModbusProtocol(_logger);
                var transport = new ModbusTcpTransport(_logger);

                // 3. 创建设备实例
                device = new ModbusDevice("Device001", "Modbus TCP设备", protocol, transport, _logger);

                // 4. 订阅事件
                device.DataReceived += OnDeviceDataReceived;
                device.ConnectionStatusChanged += OnDeviceConnectionStatusChanged;

                // 5. 连接设备
                var connectionParameters = connectionBuilder.GetParameters();
                var connectResult = await device.ConnectAsync(connectionParameters);

                if (!connectResult.Success)
                {
                    _logger?.LogError("设备连接失败: {Message}", connectResult.Message);
                    return;
                }

                _logger?.LogInformation("设备连接成功");

                // 6. 读取保持寄存器
                var readResult = await device.ReadHoldingRegistersAsync(0, 10);
                if (readResult.Success && readResult.Data != null)
                {
                    _logger?.LogInformation("读取保持寄存器成功，数据: {Data}", 
                        string.Join(", ", readResult.Data));
                }
                else
                {
                    _logger?.LogWarning("读取保持寄存器失败: {Message}", readResult.Message);
                }

                // 7. 写单个寄存器
                var writeResult = await device.WriteSingleRegisterAsync(0, 12345);
                if (writeResult.Success)
                {
                    _logger?.LogInformation("写单个寄存器成功");
                }
                else
                {
                    _logger?.LogWarning("写单个寄存器失败: {Message}", writeResult.Message);
                }

                // 8. 读取线圈状态
                var coilsResult = await device.ReadCoilsAsync(0, 16);
                if (coilsResult.Success && coilsResult.Data != null)
                {
                    _logger?.LogInformation("读取线圈状态成功，数据: {Data}", 
                        string.Join(", ", coilsResult.Data.Select(b => b ? "1" : "0")));
                }
                else
                {
                    _logger?.LogWarning("读取线圈状态失败: {Message}", coilsResult.Message);
                }

                // 9. 写单个线圈
                var coilWriteResult = await device.WriteSingleCoilAsync(0, true);
                if (coilWriteResult.Success)
                {
                    _logger?.LogInformation("写单个线圈成功");
                }
                else
                {
                    _logger?.LogWarning("写单个线圈失败: {Message}", coilWriteResult.Message);
                }

                // 10. 获取设备状态
                var deviceStatus = device.GetDeviceStatus();
                _logger?.LogInformation("设备状态: {Status}", System.Text.Json.JsonSerializer.Serialize(deviceStatus));

                // 等待一段时间以观察数据接收
                await Task.Delay(5000);

                _logger?.LogInformation("Modbus TCP通信示例完成");
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "Modbus TCP通信示例时发生异常");
            }
            finally
            {
                // 清理资源
                if (device != null)
                {
                    device.DataReceived -= OnDeviceDataReceived;
                    device.ConnectionStatusChanged -= OnDeviceConnectionStatusChanged;
                    
                    if (device.IsConnected)
                    {
                        await device.DisconnectAsync();
                    }
                    
                    device.Dispose();
                }
            }
        }

        /// <summary>
        /// Modbus RTU通信示例
        /// </summary>
        /// <returns>任务</returns>
        public async Task ModbusRtuExampleAsync()
        {
            ModbusDevice? device = null;
            try
            {
                _logger?.LogInformation("开始Modbus RTU通信示例");

                // 1. 创建连接字符串
                var connectionBuilder = new ConnectionStringBuilder(_logger)
                    .SetModbusRtuParameters("COM3", 9600, 1, 8, "One", "None", 5000);

                var connectionString = connectionBuilder.Build();
                _logger?.LogInformation("连接字符串: {ConnectionString}", connectionString);

                // 2. 创建协议和传输实例
                var protocol = new ModbusProtocol(_logger);
                var transport = new ModbusRtuTransport(_logger);

                // 3. 创建设备实例
                device = new ModbusDevice("Device002", "Modbus RTU设备", protocol, transport, _logger);

                // 4. 订阅事件
                device.DataReceived += OnDeviceDataReceived;
                device.ConnectionStatusChanged += OnDeviceConnectionStatusChanged;

                // 5. 连接设备
                var connectionParameters = connectionBuilder.GetParameters();
                var connectResult = await device.ConnectAsync(connectionParameters);

                if (!connectResult.Success)
                {
                    _logger?.LogError("设备连接失败: {Message}", connectResult.Message);
                    return;
                }

                _logger?.LogInformation("设备连接成功");

                // 6. 读取输入寄存器
                var inputRegistersResult = await device.ReadHoldingRegistersAsync(0, 5); // RTU使用同样的方法
                if (inputRegistersResult.Success && inputRegistersResult.Data != null)
                {
                    _logger?.LogInformation("读取输入寄存器成功，数据: {Data}", 
                        string.Join(", ", inputRegistersResult.Data));
                }
                else
                {
                    _logger?.LogWarning("读取输入寄存器失败: {Message}", inputRegistersResult.Message);
                }

                // 等待一段时间以观察数据接收
                await Task.Delay(3000);

                _logger?.LogInformation("Modbus RTU通信示例完成");
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "Modbus RTU通信示例时发生异常");
            }
            finally
            {
                // 清理资源
                if (device != null)
                {
                    device.DataReceived -= OnDeviceDataReceived;
                    device.ConnectionStatusChanged -= OnDeviceConnectionStatusChanged;
                    
                    if (device.IsConnected)
                    {
                        await device.DisconnectAsync();
                    }
                    
                    device.Dispose();
                }
            }
        }

        /// <summary>
        /// 使用驱动加载器的示例
        /// </summary>
        /// <returns>任务</returns>
        public async Task DriverLoaderExampleAsync()
        {
            try
            {
                _logger?.LogInformation("开始驱动加载器示例");

                // 1. 创建驱动加载器
                var driverLoader = new DriverLoader(_logger);

                // 2. 加载当前程序集（假设Modbus协议在当前程序集中）
                var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
                var assemblyPath = currentAssembly.Location;
                
                if (driverLoader.LoadAssembly(assemblyPath))
                {
                    _logger?.LogInformation("程序集加载成功: {AssemblyPath}", assemblyPath);

                    // 3. 创建协议实例
                    var protocolInstance = driverLoader.CreateProtocolInstance(
                        currentAssembly.GetName().Name ?? "Current",
                        "Uantek.Device.Communication.Protocols.Modbus.ModbusProtocol",
                        _logger);

                    if (protocolInstance != null)
                    {
                        _logger?.LogInformation("协议实例创建成功: {ProtocolName}", protocolInstance.ProtocolName);

                        // 4. 创建传输实例
                        var transportInstance = driverLoader.CreateTransportInstance(
                            currentAssembly.GetName().Name ?? "Current",
                            "Uantek.Device.Communication.Protocols.Modbus.ModbusTcpTransport",
                            _logger);

                        if (transportInstance != null)
                        {
                            _logger?.LogInformation("传输实例创建成功: {TransportType}", transportInstance.TransportType);

                            // 5. 使用动态创建的实例
                            using var device = new ModbusDevice("DynamicDevice", "动态加载设备", 
                                protocolInstance, transportInstance, _logger);

                            // 6. 获取统计信息
                            var stats = driverLoader.GetStatistics();
                            _logger?.LogInformation("驱动加载器统计信息: {Stats}", 
                                System.Text.Json.JsonSerializer.Serialize(stats));
                        }
                    }
                }

                _logger?.LogInformation("驱动加载器示例完成");
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "驱动加载器示例时发生异常");
            }
        }

        /// <summary>
        /// 批量设备管理示例
        /// </summary>
        /// <returns>任务</returns>
        public async Task BatchDeviceManagementExampleAsync()
        {
            var devices = new List<ModbusDevice>();
            try
            {
                _logger?.LogInformation("开始批量设备管理示例");

                // 1. 创建多个设备配置
                var deviceConfigs = new[]
                {
                    new { Id = "Device_TCP_001", Name = "TCP设备1", Host = "192.168.1.100", Port = 502, UnitId = (byte)1 },
                    new { Id = "Device_TCP_002", Name = "TCP设备2", Host = "192.168.1.101", Port = 502, UnitId = (byte)1 },
                    new { Id = "Device_RTU_001", Name = "RTU设备1", Port = "COM3", BaudRate = 9600, SlaveId = (byte)1 },
                    new { Id = "Device_RTU_002", Name = "RTU设备2", Port = "COM4", BaudRate = 9600, SlaveId = (byte)2 }
                };

                // 2. 批量创建和连接设备
                foreach (var config in deviceConfigs)
                {
                    try
                    {
                        ModbusDevice device;
                        Dictionary<string, object> connectionParams;

                        if (config.Id.Contains("TCP"))
                        {
                            // TCP设备
                            var protocol = new ModbusProtocol(_logger);
                            var transport = new ModbusTcpTransport(_logger);
                            device = new ModbusDevice(config.Id, config.Name, protocol, transport, _logger);

                            connectionParams = new ConnectionStringBuilder(_logger)
                                .SetModbusTcpParameters(config.Host, config.Port, config.UnitId)
                                .GetParameters();
                        }
                        else
                        {
                            // RTU设备
                            var protocol = new ModbusProtocol(_logger);
                            var transport = new ModbusRtuTransport(_logger);
                            device = new ModbusDevice(config.Id, config.Name, protocol, transport, _logger);

                            connectionParams = new ConnectionStringBuilder(_logger)
                                .SetModbusRtuParameters(config.Port, config.BaudRate, config.SlaveId)
                                .GetParameters();
                        }

                        // 订阅事件
                        device.DataReceived += OnDeviceDataReceived;
                        device.ConnectionStatusChanged += OnDeviceConnectionStatusChanged;

                        devices.Add(device);

                        // 尝试连接（实际使用中可能需要处理连接失败的情况）
                        var connectResult = await device.ConnectAsync(connectionParams);
                        _logger?.LogInformation("设备 {DeviceId} 连接结果: {Success}", 
                            config.Id, connectResult.Success);
                    }
                    catch (Exception ex)
                    {
                        _logger?.LogError(ex, "创建设备 {DeviceId} 时发生异常", config.Id);
                    }
                }

                // 3. 批量读取数据
                var readTasks = devices.Where(d => d.IsConnected).Select(async device =>
                {
                    try
                    {
                        var result = await device.ReadHoldingRegistersAsync(0, 3);
                        if (result.Success && result.Data != null)
                        {
                            _logger?.LogInformation("设备 {DeviceId} 读取数据成功: {Data}", 
                                device.DeviceId, string.Join(", ", result.Data));
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger?.LogError(ex, "设备 {DeviceId} 读取数据时发生异常", device.DeviceId);
                    }
                });

                await Task.WhenAll(readTasks);

                // 4. 获取所有设备状态
                var deviceStatuses = devices.Select(d => d.GetDeviceStatus()).ToList();
                _logger?.LogInformation("设备状态汇总: 总数 {Total}, 在线 {Online}, 离线 {Offline}",
                    deviceStatuses.Count,
                    deviceStatuses.Count(s => s.IsConnected),
                    deviceStatuses.Count(s => !s.IsConnected));

                _logger?.LogInformation("批量设备管理示例完成");
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "批量设备管理示例时发生异常");
            }
            finally
            {
                // 清理所有设备
                foreach (var device in devices)
                {
                    try
                    {
                        device.DataReceived -= OnDeviceDataReceived;
                        device.ConnectionStatusChanged -= OnDeviceConnectionStatusChanged;
                        
                        if (device.IsConnected)
                        {
                            await device.DisconnectAsync();
                        }
                        
                        device.Dispose();
                    }
                    catch (Exception ex)
                    {
                        _logger?.LogError(ex, "清理设备 {DeviceId} 时发生异常", device.DeviceId);
                    }
                }
            }
        }

        /// <summary>
        /// 运行所有示例
        /// </summary>
        /// <returns>任务</returns>
        public async Task RunAllExamplesAsync()
        {
            try
            {
                _logger?.LogInformation("开始运行所有Modbus通信示例");

                // 运行各个示例
                await ModbusTcpExampleAsync();
                await Task.Delay(1000);

                await ModbusRtuExampleAsync();
                await Task.Delay(1000);

                await DriverLoaderExampleAsync();
                await Task.Delay(1000);

                await BatchDeviceManagementExampleAsync();

                _logger?.LogInformation("所有Modbus通信示例运行完成");
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "运行Modbus通信示例时发生异常");
            }
        }

        #region 事件处理

        /// <summary>
        /// 处理设备数据接收事件
        /// </summary>
        /// <param name="sender">发送者</param>
        /// <param name="deviceData">设备数据</param>
        private void OnDeviceDataReceived(object? sender, DeviceDataModel deviceData)
        {
            try
            {
                _logger?.LogInformation("收到设备数据 - 设备ID: {DeviceId}, 数据类型: {DataType}, 时间戳: {Timestamp}",
                    deviceData.DeviceId, deviceData.DataType, deviceData.Timestamp);

                if (deviceData.IsAlarm)
                {
                    _logger?.LogWarning("设备报警 - 设备ID: {DeviceId}, 报警级别: {AlarmLevel}, 报警消息: {AlarmMessage}",
                        deviceData.DeviceId, deviceData.AlarmLevel, deviceData.AlarmMessage);
                }
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "处理设备数据接收事件时发生异常");
            }
        }

        /// <summary>
        /// 处理设备连接状态变化事件
        /// </summary>
        /// <param name="sender">发送者</param>
        /// <param name="isConnected">连接状态</param>
        private void OnDeviceConnectionStatusChanged(object? sender, bool isConnected)
        {
            try
            {
                var device = sender as ModbusDevice;
                _logger?.LogInformation("设备连接状态变化 - 设备ID: {DeviceId}, 状态: {Status}",
                    device?.DeviceId ?? "Unknown", isConnected ? "已连接" : "已断开");
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "处理设备连接状态变化事件时发生异常");
            }
        }

        #endregion
    }
}